using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using iSay.Properties;

namespace iSay
{
  public partial class iSayForm : Form
  {
    private FileInfo m_latestFile;
    private string m_folderPath;
    private string m_shellPath;
    private string m_shellArgs;
    private int m_waitInterval;
    private string m_searchString;
    private DateTime m_startedAt;

    public iSayForm()
    {
      InitializeComponent();
      UpdateStatus(true);
      SizeChanged += delegate { if (FormWindowState.Minimized == WindowState) Hide(); };
      _timer.Tick += TimerOnTick;
    }

    #region Private members

    private void UpdateStatus(bool idle)
    {
      _btnOpen.Enabled = idle;
      _btnStart.Enabled = idle;
      _btnStop.Enabled = !idle;
      string startedText = m_startedAt == DateTime.MinValue ? string.Empty : "since " + m_startedAt;
      string waitingText = string.Format("waiting {0}", startedText);
      _statusLabel.Text = string.Format("Status: {0}", (idle ? "idle" : waitingText));
      SetNotifyIconTip(_statusLabel.Text);
    }

    private void SetNotifyIconTip(string toolTipText)
    {
      if (toolTipText.Length > 63)
        toolTipText = toolTipText.Substring(0, 63);
      _notifyIcon.Text = toolTipText;
    }

    private static FileInfo GetLatestFile(string folder, string ext)
    {
      FileInfo latest = null;
      foreach (string s in Directory.GetFiles(folder, ext))
      {
        if (latest == null)
          latest = new FileInfo(s);
        else
        {
          FileInfo fileInfo = new FileInfo(s);
          if (fileInfo.CreationTime > latest.CreationTime)
            latest = fileInfo;
        }
      }
      return latest;
    }

    private static void OpenFolder(string shellExePath, string shellExeArgs)
    {
      ProcessStartInfo pInfo = new ProcessStartInfo(shellExePath);
      pInfo.Arguments = shellExeArgs;
      Process.Start(pInfo);
    }

    private void Inform(object obj)
    {
      _notifyIcon.BalloonTipTitle = "iSay";
      _notifyIcon.BalloonTipText = string.Format("Build '{0}' is ready.", ((FileInfo)obj).Name);
      _notifyIcon.BalloonTipIcon = ToolTipIcon.Info;
      _notifyIcon.ShowBalloonTip(2000);
      _notifyIcon.BalloonTipClicked += delegate
                                         {
                                           OpenFolder(Settings.Default.ShellExePath,
                                              string.Format("{0}{1}", Settings.Default.ShellExeArgs, m_folderPath));
                                         };
    }

    #endregion

    #region Events

    private void TimerOnTick(object sender, EventArgs e)
    {
      if (m_folderPath == null) m_folderPath = _comboBox.Items[0].ToString();
      FileInfo latest = GetLatestFile(m_folderPath, m_searchString);
      if (m_latestFile == null) m_latestFile = latest;
      if (latest != null)
        if (latest.CreationTime > m_latestFile.CreationTime)
        {
          new Thread(Inform).Start(latest);
          _timer.Stop();
          UpdateStatus(true);
        }
    }

    private void OnBrowse_Click(object sender, EventArgs e)
    {
      using (FolderBrowserDialog browserDialog = new FolderBrowserDialog())
      {
        browserDialog.ShowNewFolderButton = false;
        if (browserDialog.ShowDialog() == DialogResult.OK)
        {
          m_folderPath = browserDialog.SelectedPath;
          if (!_comboBox.Items.Contains((m_folderPath)))
            _comboBox.Items.Add(m_folderPath);
          _comboBox.SelectedItem = m_folderPath;
        }
      }
    }

    private void OnComboBox_TextChanged(object sender, EventArgs e)
    {
      m_folderPath = _comboBox.Text;
    }

    private void OnChooseShell_Click(object sender, EventArgs e)
    {
      OpenFileDialog openFileDialog = new OpenFileDialog();
      openFileDialog.Filter = "exe files (*.exe)|*.exe|All files (*.*)|*.*";
      openFileDialog.FilterIndex = 1;
      openFileDialog.RestoreDirectory = false;

      if (openFileDialog.ShowDialog() == DialogResult.OK)
      {
        _shellPathTB.Text = openFileDialog.FileName;
        m_shellPath = _shellPathTB.Text;
      }
    }

    private void OnShellArgsTB_TextChanged(object sender, EventArgs e)
    {
      m_shellArgs = _shellArgsTB.Text;
    }

    private void OnFileExtsTB_TextChanged(object sender, EventArgs e)
    {
      m_searchString = _searchStringTB.Text;
    }

    private void Interval_ValueChanged(object sender, EventArgs e)
    {
      m_waitInterval = (int)_intervalNumeric.Value;
    }

    private void OnOpen_Click(object sender, EventArgs e)
    {
      OpenFolder(m_shellPath, string.Format("{0}{1}", m_shellArgs, m_folderPath));
    }

    private void OnStart_Click(object sender, EventArgs e)
    {
      if (!_comboBox.Items.Contains(_comboBox.Text))
        _comboBox.Items.Add(_comboBox.Text);
      _timer.Interval = m_waitInterval * 1000;
      _timer.Start();
      m_startedAt = DateTime.Now;
      string toolTipText = string.Format("Waiting for file in {0}.", m_folderPath);
      SetNotifyIconTip(toolTipText);
      UpdateStatus(false);
    }

    private void OnStop_Click(object sender, EventArgs e)
    {
      _timer.Stop();
      UpdateStatus(true);
    }

    private void OnManageFolders_Click(object sender, EventArgs e)
    {
      ManageFoldersForm form = new ManageFoldersForm(_comboBox.Items);
      if (form.ShowDialog(this) != DialogResult.OK) return;
      _comboBox.Items.Clear();
      foreach (string s in form.Folders)
        _comboBox.Items.Add(s);
    }

    private void OnCombo_SelectedValueChanged(object sender, EventArgs e)
    {
      if (string.IsNullOrEmpty(_comboBox.SelectedItem.ToString())) return;
      m_latestFile = GetLatestFile(_comboBox.SelectedItem.ToString(), m_searchString);
      UpdateStatus(true);
    }

    private void iSayForm_Load(object sender, EventArgs e)
    {
      _shellPathTB.Text = m_shellPath = Settings.Default.ShellExePath;
      _shellArgsTB.Text = m_shellArgs = Settings.Default.ShellExeArgs;
      _searchStringTB.Text = m_searchString = Settings.Default.SearchString;
      _intervalNumeric.Value = m_waitInterval = Settings.Default.WaitInterval;
      _timer.Interval = m_waitInterval * 1000;
      if (Settings.Default.Folders != null)
        foreach (string s in Settings.Default.Folders)
          _comboBox.Items.Add(s);
      if (_comboBox.Items.Count > 0)
      {
        _comboBox.SelectedIndex = 0;
        m_folderPath = _comboBox.SelectedItem.ToString();
      }
    }

    private void iSayForm_FormClosing(object sender, FormClosingEventArgs e)
    {
      Settings.Default.Folders.Clear();
      foreach (object item in _comboBox.Items)
      {
        if (string.IsNullOrEmpty(item.ToString())) continue;
        Settings.Default.Folders.Add(item.ToString());
      }
      Settings.Default.ShellExePath = m_shellPath = _shellPathTB.Text;
      Settings.Default.ShellExeArgs = m_shellArgs = _shellArgsTB.Text;
      Settings.Default.WaitInterval = m_waitInterval = (int)_intervalNumeric.Value;
      Settings.Default.SearchString = m_searchString = _searchStringTB.Text;
      Settings.Default.Save();
    }

    private void OnNotify_Click(object sender, MouseEventArgs e)
    {
      if (e.Button == MouseButtons.Left)
      {
        Show();
        WindowState = FormWindowState.Normal;
        BringToFront();
      }
    }

    private void _menuExit_Click(object sender, EventArgs e)
    {
      Application.Exit();
    }

    #endregion

  }
}